/**
 * @file test_logger.cpp
 * @brief 日志模块测试程序
 * @author Enterprise Logger Team
 * @date 2024
 */

#include "LoggerManager.h"
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>
#include <atomic>
#include <random>

using namespace logger;

// 自定义类型测试
struct Point
{
    int x;
    int y;

    friend std::ostream& operator<<(std::ostream& os, const Point& p)
    {
        return os << "Point(" << p.x << ", " << p.y << ")";
    }
};

// 性能测试函数
void performanceTest(int threadId, int numLogs)
{
    std::random_device              rd;
    std::mt19937                    gen(rd());
    std::uniform_int_distribution<> dis(1, 100);

    auto start = std::chrono::high_resolution_clock::now();

    for (int i = 0; i < numLogs; ++i) {
        LOG_INFO << "Thread " << threadId << " | Message " << i << " | Random: " << dis(gen)
                 << " | Time: " << std::chrono::system_clock::now().time_since_epoch().count();

        // 随机插入不同级别的日志
        if (i % 10 == 0) {
            LOG_DEBUG << "Debug message from thread " << threadId << " at iteration " << i;
        }
        if (i % 50 == 0) {
            LOG_WARN << "Warning message from thread " << threadId << " at iteration " << i;
        }
        if (i % 100 == 0) {
            LOG_ERROR << "Error message from thread " << threadId << " at iteration " << i;
        }
    }

    auto end      = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

    LOG_INFO << "Thread " << threadId << " completed " << numLogs << " logs in " << duration.count()
             << "ms"
             << " (" << (numLogs * 1000.0 / duration.count()) << " logs/sec)";
}

// 基本功能测试
void basicTest()
{
    std::cout << "\n=== Basic Functionality Test ===" << std::endl;

    // 测试不同日志级别
    LOG_TRACE << "This is a TRACE message (should not appear if level is INFO)";
    LOG_DEBUG << "This is a DEBUG message (should not appear if level is INFO)";
    LOG_INFO << "This is an INFO message";
    LOG_WARN << "This is a WARNING message";
    LOG_ERROR << "This is an ERROR message";

    // 测试基本数据类型
    LOG_INFO << "Testing basic types:";
    LOG_INFO << "bool: " << true << " " << false;
    LOG_INFO << "int: " << 42 << " " << -42;
    LOG_INFO << "unsigned: " << 42u;
    LOG_INFO << "long: " << 1234567890L;
    LOG_INFO << "long long: " << 9876543210LL;
    LOG_INFO << "float: " << 3.14f;
    LOG_INFO << "double: " << 2.71828;
    LOG_INFO << "char: " << 'A';
    LOG_INFO << "C-string: " << "Hello, World!";
    LOG_INFO << "std::string: " << std::string("C++ String");

    // 测试指针
    int  value = 42;
    int* ptr   = &value;
    LOG_INFO << "Pointer: " << static_cast<void*>(ptr);
    LOG_INFO << "nullptr: " << static_cast<void*>(nullptr);

    // 测试自定义类型
    Point p{10, 20};
    LOG_INFO << "Custom type: " << p;

    // 测试组合输出
    LOG_INFO << "Mixed types: " << "String=" << "test"
             << " | Int=" << 123 << " | Float=" << 45.67 << " | Point=" << p;
}

// 日志轮转演示测试
void logRotationTest()
{
    std::cout << "\n=== Log Rotation Demo ===" << std::endl;

    LOG_INFO << "Starting log rotation demonstration...";
    LOG_INFO << "File size limit: 50KB, writing large messages to trigger rotation";

    // 写入大量日志来触发轮转
    for (int i = 0; i < 200; ++i) {
        LOG_INFO << "Log rotation test message #" << i
                 << " - This is a longer message designed to fill up the log file quickly "
                 << "and demonstrate the automatic log rotation feature. "
                 << "Current iteration: " << i << " | Timestamp: "
                 << std::chrono::duration_cast<std::chrono::milliseconds>(
                        std::chrono::system_clock::now().time_since_epoch())
                        .count();

        // 每50条消息暂停一下，让用户看到进度
        if (i % 50 == 0) {
            std::cout << "Written " << i << " messages, check logs directory for rotation..."
                      << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
    }

    LOG_INFO
        << "Log rotation demonstration completed. Check the logs directory for multiple files.";
}

// 并发测试和性能评估
void concurrencyTest()
{
    std::cout << "\n=== Concurrency & Performance Test ===" << std::endl;

    const int numThreads    = 8;
    const int logsPerThread = 500;

    std::vector<std::thread> threads;

    auto start = std::chrono::high_resolution_clock::now();

    // 启动多个线程并发写入日志
    for (int i = 0; i < numThreads; ++i) {
        threads.emplace_back(performanceTest, i, logsPerThread);
    }

    // 等待所有线程完成
    for (auto& t : threads) {
        t.join();
    }

    auto end      = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

    int totalLogs = numThreads * logsPerThread;
    std::cout << "📊 Performance Results:" << std::endl;
    std::cout << "  • Total logs: " << totalLogs << std::endl;
    std::cout << "  • Threads: " << numThreads << std::endl;
    std::cout << "  • Total time: " << duration.count() << "ms" << std::endl;
    std::cout << "  • Throughput: " << (totalLogs * 1000.0 / duration.count()) << " logs/sec"
              << std::endl;
}

// 日志轮转测试
void rotationTest()
{
    std::cout << "\n=== Log Rotation Test ===" << std::endl;

    // 生成大量日志以触发文件轮转
    for (int i = 0; i < 100000; ++i) {
        LOG_INFO << "Rotation test log #" << i
                 << " - This is a relatively long log message to fill up the file size quickly. "
                 << "The quick brown fox jumps over the lazy dog. "
                 << "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";

        if (i % 10000 == 0) {
            std::cout << "Generated " << i << " logs..." << std::endl;
        }
    }

    std::cout << "Rotation test completed. Check log files for rotation." << std::endl;
}

// 压力测试
void stressTest()
{
    std::cout << "\n=== Stress Test ===" << std::endl;

    const int numThreads    = 20;
    const int logsPerThread = 10000;

    std::atomic<int> totalLogged(0);

    auto workerFunc = [&totalLogged, logsPerThread](int threadId) {
        for (int i = 0; i < logsPerThread; ++i) {
            LOG_INFO << "Stress test - Thread: " << threadId << " | Iteration: " << i
                     << " | Total: " << totalLogged.fetch_add(1);
        }
    };

    auto start = std::chrono::high_resolution_clock::now();

    std::vector<std::thread> threads;
    for (int i = 0; i < numThreads; ++i) {
        threads.emplace_back(workerFunc, i);
    }

    for (auto& t : threads) {
        t.join();
    }

    auto end      = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::seconds>(end - start);

    std::cout << "Stress test completed: " << totalLogged.load() << " logs in " << duration.count()
              << " seconds" << std::endl;
}

int main(int argc, char* argv[])
{
    std::cout << "=== Enterprise Logger Test Suite ===" << std::endl;

    // 使用配置文件初始化日志系统
    if (!InitLoggerFromFile("config/logger.conf")) {
        std::cerr << "Failed to initialize logger from config file!" << std::endl;
        return 1;
    }

    LOG_INFO << "Logger test suite started";

    // 运行测试
    basicTest();

    // 等待一下，让异步日志有时间处理
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 日志轮转演示
    logRotationTest();

    std::this_thread::sleep_for(std::chrono::seconds(2));

    // 并发性能测试
    concurrencyTest();

    std::this_thread::sleep_for(std::chrono::seconds(1));

    // 可选的测试（根据需要启用）
    if (argc > 1 && std::string(argv[1]) == "--full") {
        rotationTest();
        std::this_thread::sleep_for(std::chrono::seconds(2));

        stressTest();
        std::this_thread::sleep_for(std::chrono::seconds(2));
    }

    LOG_INFO << "Logger test suite completed";

    // 关闭日志系统
    ShutdownLogger();

    std::cout << "\n=== All tests completed ===" << std::endl;
    std::cout << "Check the ./logs directory for log files." << std::endl;

    return 0;
}
